Lifetime (SwiftUI)
View の lifetime
State の lifetime
SwiftUI の View は値型であり、描画に反映された後保持され続けることはなく、破棄される。ただし、View の Identity や状態は SwiftUI によって適切に永続化される。この永続化の lifetime は View Identity の lifetime と一致している。
例えば、以下のような View を用意する。CountView はカウントアップができる。MyView 上では 2 つの構造上異なる位置の CountView 同士を Toggle で切り替えられる。この時、CountView をカウントアップしてから Toggle を押すと、表示される CountView の位置が変わるため、View Identity が変わり、状態も破棄され、カウントが 0 に戻ってしまう。
Toggle で切り替えた瞬間に状態が破棄されたので、例えば、カウントを10まで進めた後 Toggle をオンにして、またオフにしたとしても、10までカウントした状態には戻らない。
code:swift
import PlaygroundSupport
import SwiftUI
struct CountView: View {
@State var counter: Int = 0
var body: some View {
HStack {
Button("Press Me") { counter += 1 }
Text("\(counter)")
}
}
}
struct MyView: View {
@State var isOn: Bool = true
var body: some View {
VStack {
Toggle("Toggle Me", isOn: $isOn.animation())
.padding()
HStack {
if isOn {
CountView()
} else {
CountView()
}
}
}
}
}
PlaygroundPage.current.setLiveView(MyView())
じゃぁ以下のように Explicit Identity を与えれば状態が保持されるのか、というと、そうはならないようだった。条件が切り替わったタイミングで元の View の状態が破棄されてしまい、新しい View が初期状態で生成される。もし状態を保持したい場合は、MyView 上で状態を保持して Binding するなど、状態の保持先をより上流に持っていく必要がある。
code:swift
if isOn {
CountView().id("myId")
} else {
CountView().id("myId")
}
参考